package MuleBackend;

import java.io.DataInputStream;
import java.io.PrintStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.ServerSocket;

import javax.swing.SwingUtilities;

/**
 * A server class for use with the client class for network functionality
 * 
 * @author Phil
 */

public class Server {

  public static ServerSocket SS = null;
  public static Socket CS = null;
  
  private static String serverIP = "";

  private static final int maxClients = 4;
  private static final clientThread[] threads = new clientThread[maxClients];
  
  public static void runServer() {

	    int portNumber = 3985;
	    
	    System.out.println("Starting Server...");    
	    try {
	      serverIP = InetAddress.getLocalHost().getHostAddress();
	      SS = new ServerSocket(portNumber);
	      System.out.println("Connection successful!");
	      System.out.println("Now using port number: " + portNumber);
	    } catch (IOException e) {
	      System.out.println(e);
	    }

	    
	    while (true) {
	      try {
	        CS = SS.accept();
	        int i = 0;
	        for (i = 0; i < maxClients; i++) {
	          if (threads[i] == null) {
	            (threads[i] = new clientThread(CS, threads)).start();
	            break;
	          }
	        }
	        if (i == maxClients) {
	          PrintStream os = new PrintStream(CS.getOutputStream());
	          os.println("Server too busy. Try later.");
	          os.close();
	          CS.close();
	        }
	      } catch (IOException e) {
	        System.out.println(e);
	      }
	    }
	  
	}

  public static void main(String[] args) {

    int portNumber = 3985;
    System.out.println("Starting Server...");    
    try {
      serverIP = InetAddress.getLocalHost().getHostAddress();
      SS = new ServerSocket(portNumber);
      System.out.println("Connection successful!");
      System.out.println("Now using port number: " + portNumber);
    } catch (IOException e) {
      System.out.println(e);
    }

    
    while (true) {
      try {
        CS = SS.accept();
        int i = 0;
        for (i = 0; i < maxClients; i++) {
          if (threads[i] == null) {
            (threads[i] = new clientThread(CS, threads)).start();
            break;
          }
        }
        if (i == maxClients) {
          PrintStream os = new PrintStream(CS.getOutputStream());
          os.println("Server too busy. Try later.");
          os.close();
          CS.close();
        }
      } catch (IOException e) {
        System.out.println(e);
      }
    }
  }
}

  class clientThread extends Thread {

  private String clientName = null;
  private DataInputStream input = null;
  private PrintStream output = null;
  private Socket clientSocket = null;
  private final clientThread[] threads;
  private int maxClientsCount;

  public clientThread(Socket clientSocket, clientThread[] threads) {
    this.clientSocket = clientSocket;
    this.threads = threads;
    maxClientsCount = threads.length;
  }

  public void run() {
    int maxClientsCount = this.maxClientsCount;
    clientThread[] threads = this.threads;

    try {
      input = new DataInputStream(clientSocket.getInputStream());
      output = new PrintStream(clientSocket.getOutputStream());
      String name;
      while (true) {
    	  output.println("Enter your name.");
        name = input.readLine();
          break;
      }

      output.println(name + " has connected.");
      synchronized (this) {
        for (int i = 0; i < maxClientsCount; i++) {
          if (threads[i] != null && threads[i] == this) {
            clientName = "@" + name;
            break;
          }
        }
        for (int i = 0; i < maxClientsCount; i++) 
          if (threads[i] != null && threads[i] != this) 
            threads[i].output.println(name + " has connected.");
          
        
      }
      
      while (true) {
        String line = input.readLine();
        if (line.startsWith("/E")) 
          break;
        
          synchronized (this) {
            for (int i = 0; i < maxClientsCount; i++) 
              if (threads[i] != null && threads[i].clientName != null) 
                threads[i].output.println(name+": " + line);            
          }
        }
      synchronized (this) {
        for (int i = 0; i < maxClientsCount; i++) {
          if (threads[i] != null && threads[i] != this
              && threads[i].clientName != null) {
            threads[i].output.println(name + " has disconnected");
          }
        }
      }
      output.println("User: " + name + " has signed off.");

      
      synchronized (this) {
        for (int i = 0; i < maxClientsCount; i++) {
          if (threads[i] == this) {
            threads[i] = null;
          }
        }
      }


      input.close();
      output.close();
      clientSocket.close();
    } catch (IOException e) {
    }
  }
}
